/*
 * Author  : Leo <lipf160627@163.com>
 * Created : 2025-7-27
 * Desc    : 1.28 inch circle LCD driver
 */

#pragma once

#include "lcd_font.hpp"
#include "lcd_pic.hpp"

#include <stdint.h>
#include <string>

#include "driver/gpio.h"
#include "driver/spi_master.h"

#define USE_HORIZONTAL 0

#define LCD_HEIGHT  240
#define LCD_WIDTH   240

// 画笔颜色：16位RGB格式
#define WHITE       0xFFFF
#define BLACK       0x0000
#define BLUE        0x001F
#define BRED        0XF81F
#define GRED        0XFFE0
#define GBLUE       0X07FF
#define RED         0xF800
#define MAGENTA     0xF81F
#define GREEN       0x07E0
#define CYAN        0x7FFF
#define YELLOW      0xFFE0
#define BROWN       0XBC40 //棕色
#define BRRED       0XFC07 //棕红色
#define GRAY        0X8430 //灰色
#define DARKBLUE    0X01CF //深蓝色
#define LIGHTBLUE   0X7D7C //浅蓝色
#define GRAYBLUE    0X5458 //灰蓝色
#define LIGHTGREEN  0X841F //浅绿色
#define LGRAY       0XC618 //浅灰色(PANNEL), 窗体背景色
#define LGRAYBLUE   0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE      0X2B12 //浅棕蓝色(选择条目的反色)

typedef enum {
    FONT_1206 = 0,
    FONT_1608,
    FONT_2412,
    FONT_3216,
} Lcd_FontSize_t;

class Lcd {
public:
    Lcd(spi_host_device_t spiHost, gpio_num_t pinClk, gpio_num_t pinMosi, gpio_num_t pinRst, gpio_num_t pinDc,
        gpio_num_t pinCs, gpio_num_t pinBlk);

    uint8_t getSizeYFromFontSize(Lcd_FontSize_t size);

    void fill(const uint16_t x1, const uint16_t y1, const uint16_t x2, const uint16_t y2, const uint16_t color);
    void drawPoint(uint16_t x, uint16_t y, uint16_t color);//在指定位置画一个点
    void drawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);//在指定位置画一条线
    void drawRectangle(uint16_t x1,  uint16_t y1, uint16_t x2,  uint16_t y2, uint16_t color);//在指定位置画一个矩形
    void drawCircle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color);//在指定位置画一个圆

    void showChar(uint16_t x, uint16_t y, char num, uint16_t fc, uint16_t bc, Lcd_FontSize_t size, uint8_t mode);//显示一个字符
    void showString(uint16_t x, uint16_t y, const std::string& s, uint16_t fc, uint16_t bc, Lcd_FontSize_t size, uint8_t mode);//显示字符串
    void showIntNum(uint16_t x, uint16_t y, uint16_t num, uint8_t len, uint16_t fc, uint16_t bc, Lcd_FontSize_t size);//显示整数变量
    void showFloatNum1(uint16_t x, uint16_t y, float num, uint8_t len, uint16_t fc, uint16_t bc, Lcd_FontSize_t size);//显示两位小数变量

    void showPicture(uint16_t x, uint16_t y, uint16_t height, uint16_t width, const uint8_t pic[]);//显示图片

    void showChinese(uint16_t x, uint16_t y, char *s, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode);//显示汉字串
    void showChinese12x12(uint16_t x, uint16_t y, char *s, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode);//显示单个12x12汉字
    void showChinese16x16(uint16_t x, uint16_t y, char *s, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode);//显示单个16x16汉字
    void showChinese24x24(uint16_t x, uint16_t y, char *s, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode);//显示单个24x24汉字
    void showChinese32x32(uint16_t x, uint16_t y, char *s, uint16_t fc, uint16_t bc, uint8_t sizey, uint8_t mode);//显示单个32x32汉字

private:
    spi_host_device_t m_spiHost;

    gpio_num_t m_pinClk;
    gpio_num_t m_pinMosi;
    gpio_num_t m_pinRst;
    gpio_num_t m_pinDc;
    gpio_num_t m_pinCs;
    gpio_num_t m_pinBlk;

    void init();
    void spiInit();
    static void spiPreTransferCallback(spi_transaction_t *t);

    void setAddress(const uint16_t x1, const uint16_t y1, const uint16_t x2, const uint16_t y2);
    void writeData(const uint8_t data);
    void writeData(const uint8_t *data, size_t len);
    void writeCommand(const uint8_t cmd);
};
